#pragma once
#include "Render.h"

#ifdef BUILD_D3D9
#include <vector>
#include <string>
#include <windows.h>
#include <d3d9.h> 
#include <d3dx9.h>

#define AS_D3D9_RESOURCE(r) ((LPDIRECT3DRESOURCE9)r)
#define RELEASE_D3D9_RESOURCE(r) if(r) { AS_D3D9_RESOURCE(r)->Release(); r = NULL; }


class CD3D9 : public Render {

	static LPDIRECT3DDEVICE9	g_pd3dDevice;
	static LPDIRECT3D9			g_pD3D;
	static LPD3DXSPRITE			g_pSpriteBatch;
	static LPD3DXFONT			g_pd3dxFont;
	static bool					g_SpriteBatchActive;

	static LPD3DXEFFECT g_pCurrentShader;

protected:

	
	DeviceVersion m_Version;

public:

	bool GetShader(const std::string& filename, const uint VertexFormat, const uint Attributes, Render::tShader** pInOut = NULL, bool forceReload = true, LPVOID pTargetDevice = NULL);
	bool ReleaseShader(Render::tShader* pShader);

	void SetShaderTexture(DWORD Stage, tResource* pTexture);
	void SetProcedural(DWORD Stage,tProceduralData* pProcedural);
	bool GetTextureInfo(tResource* pTexture, UINT* pWidth, UINT* pHeight);
	bool GetBufferInfo(tResource* pBuffer, UINT* pSizeInBytes);
	bool GetTexture(const std::string& filename, Render::tResource** pOut);

	bool Create(HWND hWnd);
	bool Release();
	bool ReloadResources();

	bool CreateVertexBuffer(UINT sizeBytes, bool isStreamOut, tResource** pInOut);
	bool CreateIndexBuffer(UINT sizeBytes, tResource** pInOut);
	bool CreateVertexIndicieBuffer(UINT sizeBytes, LPVOID pData, uint vertexFormat, tResource** pVBOut, tResource** pIBOut);
	bool FillVertexBuffer(tResource* pVertexBuffer, UINT sizeInBytes, LPVOID pData);
	bool BindVertexBuffer(tResource** pVertexBuffers, UINT* elementSizes, UINT BufferCount);
	bool BindIndexBuffer(tResource* pIndexBuffer, UINT elementSize);
	bool BindStreamOutBuffer(tResource* pStreamOutBuffer, UINT elementSize);
	bool DrawIndexedTriangleList(UINT triangelCount, UINT* pInstanceCount);
	bool DrawTriangleList(UINT elementCount, UINT* pInstanceCount);
	bool DrawLineList(UINT elementCount);
	bool CreateTexture(const std::string& filename, Render::tResource** pOut = NULL, LPVOID pDevice = NULL);
	bool ReleaseResource(tResource** pResource);

	bool StreamOutBuffer(Model* pParentMesh, Render::tResource* pInstanceBuffer, UINT* pPrimitvesWritten);
	bool SetShaderMatrix(LPCSTR pName, D3DXMATRIX* pValue);
	bool SetShaderVector(LPCSTR pName, D3DXVECTOR4* pValue);
	bool SetShaderFloat(LPCSTR pName, float value);
	bool SetShaderInt(LPCSTR pName, int value);

	bool BeginShader(const Render::tShader* pShader, bool isInstanced,  UINT* pPasses);
	bool EndShader();
	bool BeginShaderPass(UINT pass);
	bool EndShaderPass();

	bool BeginSprites();
	bool EndSprites();
	void DrawSprite(tResource* pTexture, D3DXVECTOR2& position, D3DXVECTOR2& scale, RECT* pSrc);
	void DrawText(std::string& text, DWORD type, D3DCOLOR color, RECT* pSrc);

	void BeginRendering();
	void EndRendering();
};

#endif